package cn.pink.core.support.observer;

import cn.pink.core.support.SysException;
import cn.pink.core.support.function.CommonFunction;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 抽象主题
 * 功能:
 * 1.注册观察者: 在本框架中观察者是带Listener和MsgReceiver注解的方法, 分别使用GenEvent.bat, GenObserverInit.bat生成注册类. 启动时初始化.
 * 2.通知观察者: 触发msg和event事件
 * @Author: pink
 * @Date: 2022/6/29 20:14
 */
public abstract class Subject {
    /** 观察者名(事件号) -> 观察者函数列表 */
    private final Map<String, List<CommonFunction>> observers = new HashMap<>();

    /**
     * 注册事件侦听函数，此函数一般由自动生成的代码调用
     */
    public final void reg(String key, Object function, int paramSize) {
        List<CommonFunction> funcs = observers.computeIfAbsent(key, k -> new ArrayList<>());
        funcs.add(new CommonFunction(function ,paramSize));
    }

    /**
     * 通知观察者
     */
    public final void notice(Object key, Object subKey, Object param) {
        try {
            // 创建事件关键字
            // 如果有子事件 那么会创建两个事件(主事件 + 子事件)
            fire(createObserverKey(key, null), param);
            if (subKey != null) {
                fire(createObserverKey(key, subKey), param);
            }
        } catch (Exception e) {
            throw new SysException(e);
        }
    }

    /**
     * 创建观察者名(事件名)
     */
    public static String createObserverKey(Object key, Object subKey) {
        String mk = key.toString();

        // 如果有 那么拼装子事件
        if (subKey != null && !subKey.toString().equals("")) {
            mk = mk + "$" + subKey;
        }

        return mk;
    }

    private void fire(String fullKey, Object param) {
        List<CommonFunction> funcs = observers.get(fullKey);
        if (null != funcs) {
            for (CommonFunction f : funcs) {
                try {
                    f.apply(param);
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}
